package cn.smile.business.core.impl;

import cn.smile.bean.dto.core.DicInfoDTO;
import cn.smile.bean.dto.core.PickerDTO;
import cn.smile.bean.entity.core.DicInfo;
import cn.smile.bean.form.core.dic.DicAddForm;
import cn.smile.bean.form.core.dic.DicUpdateForm;
import cn.smile.bean.form.core.dic.QueryDicForm;
import cn.smile.business.core.IDicInfoService;
import cn.smile.commons.constant.NumberConstant;
import cn.smile.commons.domain.BaseServiceImpl;
import cn.smile.repository.core.DicInfoMapper;
import cn.smile.utils.BeanCopy;
import cn.smile.utils.UserUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class DicInfoServiceImpl extends BaseServiceImpl<DicInfoMapper, DicInfo> implements IDicInfoService {
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addDic(DicAddForm form) {
        log.info("[DicInfoServiceImpl].[addDic] ------> 新增字典项 Start, form = {}", JSON.toJSONString(form));
        DicInfo entity = BeanCopy.copyBean(form, DicInfo.class);
        this.setDefaultInfo(entity);
        entity.setUserId(UserUtil.getUserInfo().getId());
        super.addBaseCol(entity);
        int insertNum = baseMapper.insert(entity);
        log.info("[DicInfoServiceImpl].[addDic] ------> 新增字典项 End, insertNum = {}", insertNum);
        return insertNum > NumberConstant.ZERO;
    }

    @Override
    public Boolean updateDic(DicUpdateForm form) {
        log.info("[DicInfoServiceImpl].[updateDic] ------> 更新字典项目 Start, form = {}", JSON.toJSONString(form));
        DicInfo base = super.get(form.getId());
        base.setDicName(form.getDicName());
        boolean flag = super.update(base);
        log.info("[DicInfoServiceImpl].[updateDic] ------> 更新字典项目 End, flag = {}", flag);
        return flag;
    }

    @Override
    public List<DicInfoDTO> getDicList(String parentId) {
        return this.getDicList(parentId, UserUtil.getUserInfo().getId());
    }

    @Override
    public List<DicInfoDTO> getDicList(String parentId, String userId) {
        log.info("[DicInfoServiceImpl].[getDicList] ------> 查询字典项 Start, parentId = {}, userId = {}", parentId, userId);
        if (ObjectUtils.isEmpty(parentId)) {
            parentId = NumberConstant.MINUS_ONE_STRING;
        }
        LambdaQueryWrapper<DicInfo> qw = new QueryWrapper<DicInfo>().lambda().eq(DicInfo::getParentId, parentId).eq(DicInfo::getDeleted, Boolean.FALSE).eq(DicInfo::getIsShow, Boolean.TRUE);
        qw.eq(DicInfo::getUserId, userId);
        qw.orderByAsc(DicInfo::getDicSort);
        List<DicInfo> dicList = baseMapper.selectList(qw);
        List<DicInfoDTO> dataList;
        if (CollectionUtils.isEmpty(dicList)) {
            dataList = Lists.newArrayList();
        } else {
            dataList = BeanCopy.copyList(dicList, DicInfoDTO.class);
        }
        log.info("[DicInfoServiceImpl].[getDicList] ------> 查询字典项 End, dataList.size() = {}", dataList.size());
        return dataList;
    }

    @Override
    public Map<Integer, DicInfoDTO> getDicMap(String parentId) {
        return this.getDicMap(parentId, UserUtil.getUserInfo().getId());
    }

    @Override
    public Map<Integer, DicInfoDTO> getDicMap(String parentId, String userId) {
        log.info("[DicInfoServiceImpl].[getDicMap] ------> 查询字典项, 返回Map Start, parentId = {}, userId = {}", parentId, userId);
        Map<Integer, DicInfoDTO> dataMap = Maps.newHashMap();
        List<DicInfoDTO> dicList = this.getDicList(parentId, userId);
        if (!CollectionUtils.isEmpty(dicList)) {
            for (DicInfoDTO entity : dicList) {
                dataMap.put(entity.getDicValue(), entity);
            }
        }
        log.info("[DicInfoServiceImpl].[getDicMap] ------> 查询字典项, 返回Map End");
        return dataMap;
    }

    @Override
    public List<PickerDTO> miniProjectDicList(String parentId) {
        log.info("[DicInfoServiceImpl].[miniProjectDicList] ------> 查询字典项, 返回微信小程序对象 Start, parentId = {}", parentId);
        List<PickerDTO> dataList = Lists.newArrayList();
        List<DicInfoDTO> dicList = this.getDicList(parentId);
        if (!CollectionUtils.isEmpty(dicList)) {
            for (DicInfoDTO entity : dicList) {
                PickerDTO dto = new PickerDTO();
                dto.setLabel(entity.getDicName());
                dto.setValue(String.valueOf(entity.getDicValue()));
                dataList.add(dto);
            }
        }
        log.info("[DicInfoServiceImpl].[miniProjectDicList] ------> 查询字典项, 返回微信小程序对象 End");
        return dataList;
    }

    @Override
    public IPage<DicInfoDTO> queryPage(QueryDicForm form) {
        log.info("[DicInfoServiceImpl].[queryPage] ------> 分页查询字典项 Start, form = {}", JSON.toJSONString(form));
        LambdaQueryWrapper<DicInfo> qw = this.getQueryParams(form);
        qw.eq(DicInfo::getIsShow, Boolean.TRUE);
        Page<DicInfo> basePage = baseMapper.selectPage(form.queryPage(), qw);
        IPage<DicInfoDTO> dataPage = BeanCopy.copyPage(basePage, DicInfoDTO.class);
        log.info("[DicInfoServiceImpl].[queryPage] ------> 分页查询字典项 End");
        return dataPage;
    }

    @Override
    public Boolean delDic(String dicId) {
        log.info("[DicInfoServiceImpl].[delDic] ------> 删除数据字典项目 Start, dicId = {}", dicId);
        boolean flag = super.delById(dicId);
        log.info("[DicInfoServiceImpl].[delDic] ------> 删除数据字典项目 End, flag = {}", flag);
        return flag;
    }

    /**
     * 组装查询参数
     *
     * @param form 查询参数
     * @return 查询对象
     */
    private LambdaQueryWrapper<DicInfo> getQueryParams(QueryDicForm form) {
        LambdaQueryWrapper<DicInfo> qw = new QueryWrapper<DicInfo>().lambda().eq(DicInfo::getDeleted, Boolean.FALSE);
        if (!ObjectUtils.isEmpty(form.getDicName())) {
            qw.like(DicInfo::getDicName, form.getDicName());
        }
        if (!ObjectUtils.isEmpty(form.getParentId())) {
            qw.eq(DicInfo::getParentId, form.getParentId());
        } else {
            qw.eq(DicInfo::getParentId, NumberConstant.MINUS_ONE_STRING);
        }
        if (form.getDetailFlag()) {
            qw.eq(DicInfo::getUserId, UserUtil.getUserInfo().getId());
        }
        return qw;
    }

    /**
     * 写入默认值
     *
     * @param entity 新增对象
     */
    private void setDefaultInfo(DicInfo entity) {
        List<DicInfo> dicInfoList = baseMapper.selectList(new QueryWrapper<DicInfo>().lambda().eq(DicInfo::getParentId, entity.getParentId()).eq(DicInfo::getDeleted, Boolean.FALSE).orderByDesc(DicInfo::getDicValue));
        if (!CollectionUtils.isEmpty(dicInfoList)) {
            //存在同级字典项
            int lastValue = dicInfoList.get(NumberConstant.ZERO).getDicValue();
            if (NumberConstant.MINUS_ONE_STRING.equals(entity.getParentId())) {
                lastValue += NumberConstant.ONE_THOUSAND;
            } else {
                lastValue += NumberConstant.ONE;
            }
            entity.setDicValue(lastValue);
            //默认排最后一个
            if (ObjectUtils.isEmpty(entity.getDicSort())) {
                entity.setDicSort(dicInfoList.size() + NumberConstant.ONE);
            }
        } else {
            //不存在同级字典项
            if (NumberConstant.MINUS_ONE_STRING.equals(entity.getParentId())) {
                entity.setDicValue(NumberConstant.ONE_THOUSAND);
            } else {
                DicInfo dic = baseMapper.selectOne(new QueryWrapper<DicInfo>().lambda().eq(DicInfo::getId, entity.getParentId()).eq(DicInfo::getDeleted, Boolean.FALSE));
                entity.setDicValue(dic.getDicValue() + NumberConstant.ONE);
            }
            entity.setDicSort(NumberConstant.ONE);
        }
    }
}
